import json
import os
from typing import List, Dict, Any
from .course_task_classes import Course
from .system_modules import EnrollmentSystem
from User_Management.user_classes import Teacher, Student 
from Assignment_and_Grading.course_task_classes import Assignment  # 假设已实现
from . import config  # 导入配置
from datetime import datetime

def _ensure_data_dir():
    #确保数据存储目录存在,不存在则创建
    if not os.path.exists(config.DATA_STORAGE_PATH):
        os.makedirs(config.DATA_STORAGE_PATH)

# 获取统一的数据文件路径
def get_data_file_path():
    """获取统一的数据文件路径"""
    return os.path.join(config.PROJECT_ROOT, config.DATA_MAIN_FILE)



def course_to_dict(course: Course) -> Dict[str, Any]:
    #将Course对象转换为可序列化的字典(处理嵌套对象)
    return {
        "course_id": course.course_id,
        "course_name": course.course_name,
        "teacher_id": course.teacher.teacher_id,  # 存储教师ID(而非对象)
        "max_students": course.max_students,
        "course_description": course.course_description,  # 修改为使用getter方法
        "enrolled_students": len(course.get_enrolled_students()),
        "enrolled_student_ids": [s.student_id for s in course.get_enrolled_students()],
        "assignments": [
            {"title": a.title, "due_date": a.due_date} 
            for a in course.course_assignments
        ]
    }



def dict_to_course(course_dict: dict, teacher_map: dict, student_map: dict) -> object:
    """将字典转换为Course实例"""
    from Course_Management_and_Enrollment.course_task_classes import Course
    
    # 获取教师对象,如果不存在则创建一个临时教师对象
    teacher_id = course_dict.get("teacher_id")
    teacher = None
    
    if teacher_id:
        teacher = teacher_map.get(teacher_id)
        
    # 如果找不到教师,创建一个临时教师对象
    if not teacher:
        from User_Management.user_classes import Teacher
        temp_teacher_id = teacher_id or f"TEMP_TCH_{os.urandom(4).hex().upper()}"
        teacher = Teacher(
            user_id=f"TEMP_USER_{os.urandom(4).hex().upper()}",
            username=f"temp_teacher_{temp_teacher_id}",
            password="",
            email=f"temp_{temp_teacher_id}@example.com",
            is_encrypted=True,
            teacher_id=temp_teacher_id
        )
        teacher.role = "teacher"
        print(f"⚠️ 创建临时教师对象: {temp_teacher_id} 用于课程: {course_dict.get('course_name', 'Unknown')}")
    
    # 创建Course实例
    course = Course(
        course_id=course_dict["course_id"],
        course_name=course_dict["course_name"],
        course_description=course_dict.get("course_description", ""),
        teacher=teacher,
        max_students=course_dict.get("max_students", 30)
    )
    
    # 添加状态属性(如果不存在)
    if hasattr(course, 'status'):
        course.status = course_dict.get('status', 'approved')
    
    # 关联学生
    enrolled_students = []
    for student_id in course_dict.get("enrolled_students", []):
        student = student_map.get(student_id)
        if student:
            enrolled_students.append(student)
    course.enrolled_students = enrolled_students
    
    return course


# 修改保存课程数据的函数
def save_courses(courses: List[Course]) -> bool:
    """保存课程数据到统一的数据文件"""
    try:
        # 读取现有数据
        all_data = {}
        if os.path.exists(get_data_file_path()):
            with open(get_data_file_path(), 'r', encoding='utf-8') as f:
                all_data = json.load(f)
                
        # 更新课程数据部分
        courses_data = []
        for course in courses:
            course_info = {
                "course_id": course.course_id,
                "course_name": course.course_name,
                "teacher_id": course.teacher.teacher_id if course.teacher else None,
                "max_students": course.max_students,
                "course_description": course.course_description,
                "enrolled_students": len(course.get_enrolled_students()),
                "enrolled_student_ids": [s.student_id for s in course.get_enrolled_students()],
                "assignments": [
                    {"title": a.title, "due_date": a.due_date.isoformat()}
                    for a in course.course_assignments
                ]
            }
            courses_data.append(course_info)
        
        all_data['courses'] = courses_data
        
        # 保存完整数据
        with open(get_data_file_path(), 'w', encoding='utf-8') as f:
            json.dump(all_data, f, ensure_ascii=False, indent=2)
        print(f"课程数据已保存至:{get_data_file_path()}")
        return True
    except Exception as e:
        print(f"保存课程数据失败:{str(e)}")
        return False

# 修改加载课程数据的函数
def load_courses(teacher_map: Dict[str, Teacher], student_map: Dict[str, Student]) -> List[Course]:
    """从统一的数据文件加载课程数据"""
    try:
        file_path = get_data_file_path()
        if not os.path.exists(file_path):
            print(f"课程数据文件不存在:{file_path},返回空列表")
            return []
        
        import json
        with open(file_path, "r", encoding="utf-8") as f:
            all_data = json.load(f)
            
        courses = []
        # 加载课程数据部分
        if 'courses' in all_data:
            for course_info in all_data['courses']:

                # 从映射表中找到对应的教师对象
                teacher_id = course_info["teacher_id"]
                teacher = None
                if teacher_id:
                    # 1. 首先在教师映射中查找
                    teacher = teacher_map.get(teacher_id)
    
                    # 2. 如果没找到,尝试遍历映射表中所有值查找
                    if not teacher:
                        for t in teacher_map.values():
                            if hasattr(t, 'teacher_id') and t.teacher_id == teacher_id:
                                teacher = t
                                teacher_map[teacher_id] = teacher  # 更新映射表
                                break
    
                    # 3. 如果仍然没找到,尝试从全局用户列表查找
                    if not teacher:
                        try:
                            from User_Management.user_classes import User
                            for user in User.all_users():
                                if hasattr(user, 'teacher_id') and user.teacher_id == teacher_id:
                                    teacher = user
                                    teacher_map[teacher_id] = teacher  # 更新映射表
                                    break
                        except Exception as e:
                            print(f"尝试从全局用户列表查找教师失败: {e}")
    
                    # 4. 如果所有方法都失败,创建临时教师并打印警告
                    if not teacher:
                        print(f"警告: 教师ID {teacher_id} 不存在")
                        from User_Management.user_classes import Teacher
                        teacher = Teacher(
                            user_id=f"TEMP_USER_{teacher_id}",
                            username=f"temp_teacher_{teacher_id}",
                            password="",
                            email=f"temp_{teacher_id}@example.com",
                            is_encrypted=True,
                            teacher_id=teacher_id
                        )
                        teacher.role = "teacher"
                        teacher_map[teacher_id] = teacher
                
                # 创建课程对象
                course = Course(
                    course_id=course_info["course_id"],
                    course_name=course_info["course_name"],
                    teacher=teacher,
                    max_students=course_info["max_students"],
                    course_description=course_info["course_description"]
                )
                
                # 添加状态属性(如果不存在)
                if hasattr(course, 'status'):
                    course.status = course_info.get('status', 'approved')
                
                # 还原已选学生 - 修复字段名不匹配问题
                # 先尝试使用'enrolled_student_ids'字段,如果不存在则使用'enrolled_students'
                student_ids = course_info.get("enrolled_student_ids", [])
                if not student_ids and "enrolled_students" in course_info:
                    student_ids = course_info["enrolled_students"]
                
                for student_id in student_ids:
                    student = student_map.get(student_id)
                    if student:
                        try:
                            course._add_student(student)
                        except Exception as e:
                            print(f"添加学生 {student_id} 到课程 {course.course_id} 失败: {e}")
                
                # 还原作业
                assignments_data = course_info.get("assignments", [])
                if not assignments_data and "course_assignments" in course_info:
                    assignments_data = course_info["course_assignments"]
                
                for ass_data in assignments_data:
                    try:
                        # 根据数据类型创建作业对象
                        if isinstance(ass_data, dict) and "title" in ass_data:
                            from Assignment_and_Grading.course_task_classes import Assignment
                            due_date = ass_data["due_date"]
                            if isinstance(due_date, str):
                                due_date = datetime.fromisoformat(due_date)
                            assignment = Assignment(title=ass_data["title"], 
                                                  due_date=due_date)
                            course.add_assignment(assignment)
                        elif isinstance(ass_data, str):
                            # 改进字符串形式作业ID的处理,尝试从全局作业数据中查找
                            print(f"处理字符串形式的作业ID: {ass_data}")
                            # 尝试从全局作业数据中查找
                            if 'assignments' in all_data:
                                for global_ass in all_data['assignments']:
                                    if global_ass.get('assignment_id') == ass_data:
                                        from Assignment_and_Grading.course_task_classes import Assignment
                                        due_date = global_ass["due_date"]
                                        if isinstance(due_date, str):
                                            due_date = datetime.fromisoformat(due_date)
                                        # 创建一个基本的Course对象引用
                                        course_obj = type('Course', (object,), {"course_id": course.course_id})
                                        # 正确创建Assignment实例,使用正确的参数名和数量
                                        assignment = Assignment(
                                            assignment_id=ass_data, 
                                            assignment_title=global_ass.get("title", ass_data),
                                            assignment_content=global_ass.get("content", "No content"),
                                            due_date_str=global_ass["due_date"], # 使用原始字符串格式的日期
                                            course=course_obj,
                                            required_format="Any"
                                        )
                                        # 设置assignment_id(如果需要)
                                        if hasattr(assignment, 'assignable_id'):
                                            assignment.assignable_id = ass_data
                                        course.add_assignment(assignment)
                                        print(f"成功从全局作业数据中找到并添加作业: {ass_data}")
                                        break
                    except Exception as e:
                        print(f"创建作业失败: {e}")
                
                courses.append(course)
        
        print(f"✅ 加载了 {len(courses)} 个课程")
        return courses
    except json.JSONDecodeError:
        print("警告: 课程数据文件格式错误")
        return []
    except Exception as e:
        print(f"加载课程数据失败:{str(e)}")
        return []

# 修改 load_courses_and_enrollment 函数
def load_courses_and_enrollment(teachers, students, existing_courses=None):
    """加载课程和选课数据"""
    try:
        # 增强教师映射表 - 同时使用user_id和teacher_id作为键
        teacher_map = {}
        for teacher in teachers:
            if hasattr(teacher, 'teacher_id'):
                teacher_map[teacher.teacher_id] = teacher
            if hasattr(teacher, 'user_id'):
                teacher_map[teacher.user_id] = teacher
        
        # 增加一个临时映射来解决教师ID大小写不匹配或格式问题
        for teacher in teachers:
            if hasattr(teacher, 'teacher_id'):
                # 存储原始的teacher_id到映射表中,确保能找到教师
                teacher_id = teacher.teacher_id
                teacher_map[teacher_id] = teacher
        
        # 创建学生映射表
        student_map = {}
        for student in students:
            if hasattr(student, 'student_id'):
                student_map[student.student_id] = student
            if hasattr(student, 'user_id'):
                student_map[student.user_id] = student
        
        # 加载课程数据
        courses = load_courses(teacher_map, student_map)
        
        # 创建选课系统
        enrollment_system = EnrollmentSystem()
        
        # 初始化选课记录
        for course in courses:
            course_id = course.course_id
            # 从学生对象中获取选课信息
            enrolled_student_ids = [student.student_id for student in course.get_enrolled_students()]
            if enrolled_student_ids:
                enrollment_system._enrollment_records[course_id] = enrolled_student_ids
                
                # 更新学生选课记录
                for student_id in enrolled_student_ids:
                    if student_id not in enrollment_system.student_enrollments:
                        enrollment_system.student_enrollments[student_id] = []
                    enrollment_system.student_enrollments[student_id].append(course_id)
        
        # 返回正确的元组格式
        return (courses, enrollment_system)
    except Exception as e:
        print(f"加载课程和选课数据时出错: {e}")
        # 即使出错也返回有效的默认值
        return ([], EnrollmentSystem())


def save_enrollments(enrollment_system: EnrollmentSystem) -> bool:
    #保存选课系统记录到文件
    try:
        _ensure_data_dir()
        file_path = os.path.join(config.DATA_STORAGE_PATH, config.ENROLLMENT_DATA_FILE)
        # 直接序列化记录(已为字典格式)
        with open(file_path, "w", encoding="utf-8") as f:
            json.dump(enrollment_system.get_enrollment_records(), f, ensure_ascii=False, indent=2)
        print(f"Successfully keep enrollment record {file_path}")
        return True
    except Exception as e:
        print(f"Keep enrollment record fail:{str(e)}")
        return False


def load_enrollments(enrollment_system: EnrollmentSystem) -> bool:
    #从文件加载选课记录到系统
    try:
        file_path = os.path.join(config.DATA_STORAGE_PATH, config.ENROLLMENT_DATA_FILE)
        if not os.path.exists(file_path):
            print("Enrollment record file not exist,no need to load")
            return True
        
        with open(file_path, "r", encoding="utf-8") as f:
            records = json.load(f)
        
        # 覆盖系统中的记录(实际应用可能需要合并,这里简化为替换)
        enrollment_system._enrollment_records = records
        print(f"Successfully load enrollment record ({len(records)} courses have enroll record)")
        return True
    except Exception as e:
        print(f"Load enrollment record fail:{str(e)}")
        return False
    